﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using MahApps.Metro.Controls;
using System.IO;
using MahApps.Metro;
using System.Windows.Media.Animation;
using System.Threading;
using System.ComponentModel;

namespace intelliEssay.Graphics.Shell
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : MetroWindow
    {
        public static MainWindow Create()
        {
            MainWindow mw = new MainWindow();
            mw.LanguageBox.ItemsSource = Environment.SupportedLanguages;
            mw.shellResourceDictionary = Environment.SettingFile.ResourceDictionary;
            mw.InitTextForGlobalizaion();
            if (System.Diagnostics.Debugger.IsAttached)
            {
                mw.aminmationDebuggerAttachedWarning.Visibility = Visibility.Visible;
            }
            return mw;
        }
        public intelliEssay.Graphics.Globalization.ResourceDictionary shellResourceDictionary;
        enum GuideState : uint
        {
            OOB0 = 1,
            Overview = 2,
            DragingFile = 4,
            SelectingChecker = 8,
            SelectingStandardFormat = 16,
            WaitingForResult = 32,
            ViewingResult = 64,
            OOB1 = 128
        }
        public MainWindow()
        {
            InitializeComponent();
            (Resources["TransistAway"] as Storyboard).Completed += UI_DrawText;
            CheckerSelector.ItemsSource = Environment.LoadedComponents.Where<Core.Platform.Component>(comp =>
            {
                return comp.Type == "Checker";
            });
        }

        public void InitTextForGlobalizaion()
        {
            UI_DrawText(null, null);

            standardFormatInUseBanner.Text = shellResourceDictionary["SelectingStandardFormatStandardFormatInUse"];
            standardFormatPath.Text = GraphicsSetting.Default.StandardFile;
            AccentColorGuide.Text = shellResourceDictionary["OverviewAccentGuide"];
            bannerSummary.Text = shellResourceDictionary["BannerSummary"];
            bannerDetail.Text = shellResourceDictionary["BannerDetail"];
            visitSite.Content = shellResourceDictionary["visitsite"];
            GoUp.Content = shellResourceDictionary["PreviousStep"];
            GoDown.Content = shellResourceDictionary["NextStep"];

            setting.Text = shellResourceDictionary["setting"];

            ResetStandardFileValidation();

            //PleaseWait.Text = shellResourceDictionary["PleaseWait"];

            LanguageLabel.Content = shellResourceDictionary["language"];
            LanguageBox.Text = shellResourceDictionary["currentlanguage"];
            FlavorTile.Title = shellResourceDictionary["Changeflavor"];
            Flyouts[0].Header = shellResourceDictionary["appearance"];
            ThemeReverseTile.Title = shellResourceDictionary["fliptheme"];
            TakeAffectNextTimeTextBlock.Text = shellResourceDictionary["LangTakeAffectNextTime"];
        }

        private void ResetStandardFileValidation()
        {
            if (GraphicsSetting.Default.StandardFile == null || GraphicsSetting.Default.StandardFile == "")
            {
                validateOrPickStandardFile.Content = shellResourceDictionary["SelectingStandardFormatRepick"];
                errMsg.Text = shellResourceDictionary["SelectingStandardFormatMustSelectFile"];
            }
            else
            {
                validateOrPickStandardFile.Content = shellResourceDictionary["SelectingStandardFormatValidate"];
                errMsg.Text = shellResourceDictionary["SelectingStandardFormatValidateFile"];
            }
        }

        void UI_DrawText(object sender, EventArgs e)
        {
            summary3.Text = "";
            detail3.Text = "";
            switch (guideState)
            {
                case GuideState.DragingFile:
                    {
                        Summary1.Text = string.Format(shellResourceDictionary["DragSummary1"], filePaths.Count);
                        detail1.Text = "";
                        Summary2.Text = shellResourceDictionary["DragSummary2"];
                        detail2.Text = filePaths.AccumulatedString();
                        summary3.Text = detail3.Text = "";
                        break;
                    }
                case GuideState.Overview:
                    {
                        Summary1.Text = shellResourceDictionary["OverviewSummary1"];
                        detail1.Text = shellResourceDictionary["OverviewDetail1"];
                        Summary2.Text = shellResourceDictionary["OverviewSummary2"]; ;
                        detail2.Text = shellResourceDictionary["OverviewDetail2"];
                        summary3.Text = shellResourceDictionary["OverviewSummary3"];
                        detail3.Text = shellResourceDictionary["OverviewDetail3"];
                        break;
                    }
                case GuideState.SelectingStandardFormat:
                    {
                        Summary1.Text = shellResourceDictionary["SelectingStandardFormatSummary1"];
                        detail1.Text = shellResourceDictionary["SelectingStandardFormatDetail1"];
                        break;
                    }
                case GuideState.SelectingChecker:
                    {
                        Summary1.Text = shellResourceDictionary["SelectingCheckerSummary1"];
                        detail1.Text = shellResourceDictionary["SelectingCheckerDetail1"];
                        Summary2.Text = shellResourceDictionary["SelectingCheckerSummary2"];
                        detail2.Text = shellResourceDictionary["SelectingCheckerDetail2"]; ;
                        break;
                    }
            }
            (Resources["TransistIn"] as Storyboard).Begin();
        }

        private void UI_Overview()
        {
            GoDown.Content = shellResourceDictionary["nextstep"];
            GoUp.Visibility = System.Windows.Visibility.Collapsed;
            GoDown.Visibility = System.Windows.Visibility.Visible;
            guideState = GuideState.Overview;
            GoUp.Visibility = System.Windows.Visibility.Collapsed;
            CheckerSelector.Visibility = System.Windows.Visibility.Collapsed;
            bannerBack.Visibility = System.Windows.Visibility.Visible;
            MainGrid.AllowDrop = false;
            AccentColorGuide.Text = shellResourceDictionary["OverviewAccentGuide"];
            bannerSummary.Text = shellResourceDictionary["bannersummary"];
            bannerDetail.Text = shellResourceDictionary["bannerdetail"];
            (Resources["TransistAway"] as Storyboard).Begin();
        }


        private void UI_DraggingFile()
        {
            AccentColorGuide.Text = shellResourceDictionary["dragaccentguide"];
            GoUp.Visibility = System.Windows.Visibility.Visible;
            GoDown.Content = shellResourceDictionary["nextstep"];
            MainGrid.AllowDrop = true;
            if (filePaths.Count == 0)
            {
                GoDown.Visibility = System.Windows.Visibility.Collapsed;
            }
            bannerBack.Visibility = System.Windows.Visibility.Visible;
            CheckerSelector.Visibility = System.Windows.Visibility.Collapsed;
            (Resources["TransistAway"] as Storyboard).Begin();
        }

        private void UI_SelectChecker()
        {
            GoDown.Content = shellResourceDictionary["nextstep"];
            GoUp.Visibility = System.Windows.Visibility.Visible;
            GoDown.Visibility = System.Windows.Visibility.Visible;
            AccentColorGuide.Text = shellResourceDictionary["SelectingCheckerAccentGuide"];
            MainGrid.AllowDrop = false;
            bannerBack.Visibility = System.Windows.Visibility.Collapsed;
            CheckerSelector.Visibility = System.Windows.Visibility.Visible;
            standardFormat.Visibility = System.Windows.Visibility.Collapsed;
            (Resources["TransistAway"] as Storyboard).Begin();
        }

        private void UI_TaskSettings()
        {
            GoDown.Visibility = System.Windows.Visibility.Collapsed;
            GoUp.Visibility = System.Windows.Visibility.Visible;
            AccentColorGuide.Text = shellResourceDictionary["SelectingStandardFormatAccentGuide"];
            CheckerSelector.Visibility = System.Windows.Visibility.Collapsed;
            standardFormat.Visibility = System.Windows.Visibility.Visible;
            ResetStandardFileValidation();
            GoDown.Content = shellResourceDictionary["StartChecking"];
            (Resources["TransistAway"] as Storyboard).Begin();

        }

        private void UI_ShowResult()
        {
            results.Visibility = System.Windows.Visibility.Visible;
            transistGrid.Visibility = System.Windows.Visibility.Collapsed;
            standardFormat.Visibility = System.Windows.Visibility.Collapsed;
            GoDown.Content = shellResourceDictionary["restart"];
            AccentColorGuide.Visibility = System.Windows.Visibility.Collapsed;
            GoDown.IsEnabled = true;
        }

        GuideState guideState = GuideState.Overview;
        List<string> filePaths = new List<string>();
        private void Grid_Drop_1(object sender, DragEventArgs e)
        {
            AccentColorGuide.Text = shellResourceDictionary["DragAccentGuide"];
            var DraggedFiles = e.Data.GetData(System.Windows.DataFormats.FileDrop) as string[];
            List<string> failedPath = new List<string>();
            MainGrid.AllowDrop = false;
            ThreadPool.QueueUserWorkItem(o =>
            {
                var result = false;
                if (DraggedFiles != null)
                {
                    foreach (string str in DraggedFiles)
                    {
                        result = Core.DocumentStructure.DocumentStructure.IsValidOpenXmlFile(str);
                        Dispatcher.Invoke(new Action(() =>
                            {
                                if (result == false || filePaths.Contains(str))
                                {
                                    failedPath.Add(str);
                                }
                                else
                                {
                                    filePaths.Add(str);
                                }
                            }));
                    }
                }
                Dispatcher.Invoke(new Action(() =>
                    {
                        if (filePaths.Count > 1)
                        {
                            Summary2.Text = shellResourceDictionary["DragSummary2"];
                            detail2.Text = filePaths.AccumulatedString();
                        }
                        else if (filePaths.Count == 1)
                        {
                            if (failedPath.Count == 0)
                            {
                                Summary2.Text = shellResourceDictionary["DragSummary2"];
                                detail2.Text = filePaths.AccumulatedString();
                            }
                            else
                            {
                                Summary2.Text = shellResourceDictionary["FormatErrorOrInQueueSummary"];
                                detail2.Text = shellResourceDictionary["FormatErrorOrInQueueDetail"];
                            }

                        }
                        Summary1.Text = string.Format(shellResourceDictionary["Dragsummary1"], filePaths.Count);
                        detail1.Text = shellResourceDictionary["dragdetail1"];
                        summary3.Text = shellResourceDictionary["dragsummary3"];
                        detail3.Text = failedPath.AccumulatedString();
                        MainGrid.AllowDrop = true;
                        if (filePaths.Count > 0)
                        {
                            GoDown.Visibility = System.Windows.Visibility.Visible;
                        }
                    }));
            });


        }

        private void Grid_DragOver_1(object sender, DragEventArgs e)
        {
            AccentColorGuide.Text = shellResourceDictionary["DragLoose"];
        }

        private void Grid_DragLeave_1(object sender, DragEventArgs e)
        {
            AccentColorGuide.Text = shellResourceDictionary["DragAccentGuide"];
        }

        BackgroundWorker backgroundWorker;


        private void GoDown_Click_1(object sender, RoutedEventArgs e)
        {
            switch (guideState)
            {
                case GuideState.WaitingForResult:
                    {
                        //abort task
                        if (backgroundWorker.IsBusy)
                        {
                            GoDown.IsEnabled = false;
                            transitioning.Content = shellResourceDictionary["Cancel"] + "...";
                            backgroundWorker.CancelAsync();
                        }

                        return;
                    }
            }
            guideState = (GuideState)((uint)guideState * 2);
            switch (guideState)
            {
                case GuideState.DragingFile:
                    {
                        UI_DraggingFile();
                        break;
                    }
                case GuideState.SelectingChecker:
                    {
                        UI_SelectChecker();
                        break;
                    }
                case GuideState.SelectingStandardFormat:
                    {
                        UI_TaskSettings();
                        break;
                    }
                case GuideState.WaitingForResult:
                    {
                        GoDown.Content = shellResourceDictionary["cancel"];
                        GoUp.Visibility = System.Windows.Visibility.Collapsed;
                        transitioning.Content = shellResourceDictionary["PleaseWait"];
                        backgroundWorker = new BackgroundWorker();
                        backgroundWorker.WorkerSupportsCancellation = true;
                        backgroundWorker.WorkerReportsProgress = true;
                        backgroundWorker.DoWork += backgroundWorker_DoWork;
                        backgroundWorker.RunWorkerCompleted += backgroundWorker_RunWorkerCompleted;
                        backgroundWorker.ProgressChanged += backgroundWorker_ProgressChanged;
                        backgroundWorker.RunWorkerAsync();
                        (this.Resources["SuperBusy"] as Storyboard).Begin();
                        break;
                    }
                case GuideState.ViewingResult:
                    {
                        GoDown.Content = shellResourceDictionary["restart"];
                        break;
                    }
                case GuideState.OOB1:
                    {
                        MainWindow.Create().Show();
                        this.Close();
                        break;
                    }
            }
        }

        void backgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            if (backgroundWorker.CancellationPending == false)
            {
                this.Dispatcher.BeginInvoke(new Action(() =>
                    {
                        if (transitioning_Doc.Content != e.UserState as string)
                        {
                            transitioning_Doc.Content = e.UserState as string;
                        }
                        if (transitioning.Content != e.ProgressPercentage.ToString() + "%")
                        {
                            transitioning.Content = e.ProgressPercentage.ToString() + "%";
                        }
                    }));
            }
        }

        void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (e.Error == null)
            {
                foreach (var tsk in tasks)
                {
                    tsk.GetEssayExceptionCollectionSnapShot().Merge();
                    //tsk.Dispose();
                }
            }
            this.Dispatcher.BeginInvoke(new Action(() =>
                {
                    if (e.Error != null)
                    {
                        MessageBox.Show("Error executing. Debug your checker separately.");
                        System.Diagnostics.Debugger.Launch();
                    }
                    foreach (var tsk in tasks)
                    {
                        results.Items.Add(new TabItem() { Content = new ListBox() { ItemsSource = tsk.GetEssayExceptionCollectionSnapShot().Merge() }, Header = tsk.UserFriendlyIndentifer });
                        tsk.Dispose();
                    }
                    ((Storyboard)Resources["SuperBusy"]).Stop();
                    UI_ShowResult();
                    guideState = GuideState.ViewingResult;
                    results.SelectedIndex = 0;
                }));
        }
        List<intelliEssay.Core.Task> tasks = new List<Core.Task>();
        void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            intelliEssay.Core.TaskRuntimeExceptionCollection taskRuntimeExceptionCollection = new Core.TaskRuntimeExceptionCollection();
            foreach (string str in filePaths)
            {
                try
                {
                    backgroundWorker.ReportProgress(0, str);
                    if (backgroundWorker.CancellationPending)
                    {
                        return;
                    }
                    intelliEssay.Core.Task task = new Core.Task();
                    task.FilePath = str;
                    task.taskType = "nkub";
                    this.Dispatcher.Invoke(new Action(() =>
                        {
                            task.taskSetting.StandardFormatDocumentPath = standardFormatPath.Text;
                            foreach (var selectedItem in CheckerSelector.SelectedItems)
                            {
                                task.AddAChecker((selectedItem as intelliEssay.Core.Platform.CheckerComponent).Checker);
                            }
                        }));
                    task.OnTaskProgress += task_OnTaskProgress;
                    task.Initialize();
                    task.Run();
                    tasks.Add(task);
                }
                catch (intelliEssay.Core.TaskRuntimeException ex)
                {
                    taskRuntimeExceptionCollection.Add(ex);
                    continue;
                }
                if (taskRuntimeExceptionCollection.Count != 0)
                {
                    foreach (var runtimeException in taskRuntimeExceptionCollection)
                    {
                        throw runtimeException;
                    }
                }
            }
        }

        void task_OnTaskProgress(object sender, Core.TaskProgressed e)
        {
            backgroundWorker.ReportProgress(e.ReportedPercentage, (sender as Core.Task).FilePath);
        }


        private void GoUp_Click_1(object sender, RoutedEventArgs e)
        {
            guideState = (GuideState)((uint)guideState / 2);
            switch (guideState)
            {
                case GuideState.SelectingChecker:
                    {
                        UI_SelectChecker();
                        break;
                    }
                case GuideState.DragingFile:
                    {
                        UI_DraggingFile();
                        break;
                    }
                case GuideState.Overview:
                    {
                        UI_Overview();
                        break;
                    }
            }


        }

        private void TextBlock_PreviewMouseLeftButtonDown_1(object sender, MouseButtonEventArgs e)
        {
            if (guideState != GuideState.ViewingResult)
            {
                Flyouts[0].IsOpen = true;
            }
        }
        int ThemeRotator = 0;
        Accent currentAccent = ThemeManager.DefaultAccents.ToArray()[0];
        Theme theme = Theme.Light;
        private void Tile_Click_1(object sender, RoutedEventArgs e)
        {
            currentAccent = ThemeManager.DefaultAccents.ToArray()[++ThemeRotator % 5];
            ThemeManager.ChangeTheme(this, currentAccent, theme);
        }

        private void Tile_Click_2(object sender, RoutedEventArgs e)
        {
            theme = Theme.Light == theme ? Theme.Dark : Theme.Light;
            ThemeManager.ChangeTheme(this, currentAccent, theme);
        }

        private void validateOrPickStandardFile_Click_1(object sender, RoutedEventArgs e)
        {
            if (validateOrPickStandardFile.Content.ToString() == shellResourceDictionary["SelectingStandardFormatValidate"])
            {
                fileValidation.Visibility = System.Windows.Visibility.Visible;
                System.Threading.ThreadPool.QueueUserWorkItem(o =>
                    {
                        var result = intelliEssay.Core.DocumentStructure.DocumentStructure.IsValidOpenXmlFile(GraphicsSetting.Default.StandardFile);
                        this.Dispatcher.Invoke(new Action(() =>
                        {
                            if (result)
                            {
                                errMsg.Text = shellResourceDictionary["SelectingStandardFormatValidateSuccess"];
                                GoDown.Visibility = System.Windows.Visibility.Visible;
                            }
                            else
                            {
                                errMsg.Text = shellResourceDictionary["SelectingStandardFormatValidateFail"];
                                GoDown.Visibility = System.Windows.Visibility.Collapsed;
                            }
                            validateOrPickStandardFile.Content = shellResourceDictionary["SelectingStandardFormatRepick"];
                            fileValidation.Visibility = System.Windows.Visibility.Collapsed;
                        }));
                    });
            }
            else
            {
                Microsoft.Win32.OpenFileDialog openFilediag = new Microsoft.Win32.OpenFileDialog();
                bool? picked = openFilediag.ShowDialog();
                if (picked.Value)
                {
                    validateOrPickStandardFile.Content = shellResourceDictionary["SelectingStandardFormatValidate"];
                    standardFormatPath.Text = openFilediag.FileName;
                    errMsg.Text = shellResourceDictionary["SelectingStandardFormatValidateFile"];
                    GraphicsSetting.Default.StandardFile = openFilediag.FileName;
                }
            }
        }

        private void LanguageBox_SelectionChanged_1(object sender, SelectionChangedEventArgs e)
        {
            Environment.SettingFile.DisplayCulture = Environment.SupportedLanguageIDs[LanguageBox.SelectedIndex];
        }
    }
    static class extension
    {
        public static string AccumulatedString(this IEnumerable<string> paths)
        {
            StringBuilder sb = new StringBuilder();
            foreach (string str in paths)
            {
                sb.AppendLine(str);
            }
            return sb.ToString();
        }
    }
}
